using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

using TrueCode.DependencyManager.BuildActions.Instantiating;


namespace TrueCode.DependencyManager.Services.Instantiating
{
  public class MostParametersCountCtorProvider : IConstructorProvider
  {
    public ConstructorInfo GetConstructor( Type type )
    {
      var constructors = type.GetConstructors();

      #region Assert that constructors is not empty is type is class (not struct)
      if( constructors.Length == 0 && !type.IsValueType )
      {
        var exc = new ArgumentException( "This type does not contain any constructors", "type" );
        exc.Data.Add( "Type", type );
        throw exc;
      }
      #endregion

      ConstructorInfo constructor = null;
      if( constructors.Length > 0 ) // value type may not contain any constructor
      {
        var suitConstructors = new Dictionary< int, int > {{0, constructors[ 0 ].GetParameters().Length}};
        for( var i = 1; i < constructors.Length; i++ )
        {
          var paramentersCount = constructors[ i ].GetParameters().Length;

          var maxParametersCount = suitConstructors.First().Value;
          if( paramentersCount == maxParametersCount )
            suitConstructors.Add( i, paramentersCount );
          else if( paramentersCount > maxParametersCount )
          {
            suitConstructors.Clear();
            suitConstructors.Add( i, paramentersCount );
          }
        }

        #region Assert that there is only one suit constructor
        if( suitConstructors.Count != 1 )
        {
          var exc =
            new ArgumentException(
              "This type contains two or more constructors contains the same, most parameters count",
              "type" );
          exc.Data.Add( "Type", type );

          var counter = 0;
          foreach( var pair in suitConstructors )
            exc.Data.Add( "Constructor" + counter++, constructors[ pair.Key ] );
          throw exc;
        }
        #endregion

        constructor = constructors[ suitConstructors.First().Key ];
      }
      return constructor;
    }
  }
}